package base_app

import (
	baseLog "gitee.com/zaiqiang231/go-base-app/base_app/log"
	"github.com/fatih/color"
	"os"
	"os/signal"
	"sync"
	"syscall"
)

type ShutdownCallback interface {
	OnShutdown() error
}

type ShutdownFunc func() error

func (f ShutdownFunc) OnShutdown() error {
	return f()
}

type ErrorHandler interface {
	OnError(err error)
}

type GracefulShutdown struct {
	callbacks    []ShutdownCallback
	errorHandler ErrorHandler
}

func NewGracefulShutdown() *GracefulShutdown {
	return &GracefulShutdown{
		callbacks: make([]ShutdownCallback, 0, 10),
	}
}

func (gs *GracefulShutdown) AddShutdownCallback(shutdownCallback ShutdownCallback) {
	gs.callbacks = append(gs.callbacks, shutdownCallback)
}

func (gs *GracefulShutdown) SetErrorHandler(errorHandler ErrorHandler) {
	gs.errorHandler = errorHandler
}

func (gs *GracefulShutdown) Start() error {
	go func() {
		baseLog.Debugf("GracefulShutdown Start Work")
		c := make(chan os.Signal, 2)
		sig := make([]os.Signal, 2)
		sig[0] = os.Interrupt
		sig[1] = syscall.SIGTERM
		signal.Notify(c, sig...)
		<-c
		go func() {
			gs.StartShutdown()
		}()
		<-c
		baseLog.Fatalf("%v GracefulShutdown 强制退出", color.RedString("Error:"))
	}()
	return nil
}

func (gs *GracefulShutdown) StartShutdown() {
	baseLog.Debugw("GracefulShutdown StartShutdown", "callback_size", len(gs.callbacks))
	var wg sync.WaitGroup
	for _, shutdownCallback := range gs.callbacks {
		wg.Add(1)
		go func(callback ShutdownCallback) {
			defer wg.Done()
			gs.ReportError(callback.OnShutdown())
		}(shutdownCallback)
	}
	wg.Wait()
}

func (gs *GracefulShutdown) ReportError(err error) {
	if err != nil {
		if gs.errorHandler != nil {
			gs.errorHandler.OnError(err)
		} else {
			baseLog.Errorf("GracefulShutdown ReportError %v", err)
		}
	}
}
